﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Linq;
using System.Web.Services;
using System.IO;
using DB;
using MarshalClasses;
using Album=MarshalClasses.Album;
using MObject=MarshalClasses.MObject;
using Tag=MarshalClasses.Tag;
using User=MarshalClasses.User;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MediaWS : WebService 
{
    [WebMethod]
    public List<User> GetUsers()
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            return DBReWrapper<DB.User, User>.Rewrap(c.Users);
        }
    }   
 
    [WebMethod]
    public List<Tag> GetTags()
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            return DBReWrapper<DB.Tag, Tag>.Rewrap(c.Tags);
        }
    }

    [WebMethod]
    public TagTreeInfo GetTagTree()
    {
        return TagTreeInfo.FromList(GetTags());
    }

    [WebMethod]
    public List<Album> GetUserAlbums(int userID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            return DBReWrapper<DB.Album, Album>.Rewrap(from a in c.Albums where a.OwnerUserRef == userID select a);
        }
    }

    [WebMethod]
    public List<MObject> GetAlbumObjects(int albumID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            return DBReWrapper<DB.MObject, MObject>.Rewrap(from o in c.MObjects where o.ParentAlbumRef == albumID select o);
        }
    }

    [WebMethod]
    public List<Tag> GetObjectTags(int objID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            return DBReWrapper<DB.Tag, Tag>.Rewrap(from t in c.Tags
                let tagIds = from tr in c.MObjectTagRelations 
                             where tr.ObjectRef == objID 
                             select tr.TagRef
                where tagIds.Contains(t.ID)
                select t);
        }
    }

    [WebMethod]
    public void AssignTagToObject(int objID, int tagID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            c.MObjectTagRelations.InsertOnSubmit(new MObjectTagRelation
            {
                ObjectRef = objID,
                TagRef = tagID
            });        
            c.SubmitChanges(ConflictMode.ContinueOnConflict);
        }
    }

    [WebMethod]
    public void UnAssignTagFromObject(int objID, int tagID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            var item = new List<MObjectTagRelation>(from a in c.MObjectTagRelations
                       where a.ObjectRef == objID && a.TagRef == tagID
                       select a);
            if (item.Count > 0)
            {
                c.MObjectTagRelations.DeleteOnSubmit(item[0]);
                c.SubmitChanges(ConflictMode.ContinueOnConflict);
            }
        }
    }

    [WebMethod]
    public List<MObject> GetObjectsByTag(int tagID, bool recurse)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            IEnumerable<DB.MObject> res;

            if (tagID == 0)
            {
                if (recurse)
                    res = c.MObjects;
                else
                    res = from obj in c.MObjects
                          let tIDs = from t in c.MObjectTagRelations
                                     where t.ObjectRef == obj.ID
                                     select t
                          where tIDs.Count() == 0
                          select obj;
            }
            else
            {
                if (recurse)

                {
                    res = from obj in c.MObjects
                          where c.GetTagSubTree(tagID).Select(r => r.ID).Contains(obj.ID)
                          select obj;
                }
                else
                {
                    res = from o in c.MObjects
                          let objIds = from tr in c.MObjectTagRelations
                                       where tr.TagRef == tagID
                                       select tr.ObjectRef
                          where objIds.Contains(o.ID)
                          select o;
                }
            }

            return new List<MObject>(DBReWrapper<DB.MObject, MObject>.Rewrap(res));                
        }        
    }

    [WebMethod]
    public void DeleteObject(int objID)
    {
        using (var c = DBUtils.CreateDataAbstaction())
        {
            var item = new List<DB.MObject>(from a in c.MObjects
                                         where a.ID == objID
                                         select a);
            if (item.Count > 0)
            {
                c.MObjects.DeleteOnSubmit(item[0]);
                c.SubmitChanges(ConflictMode.FailOnFirstConflict);
            }
        }
    }

    [WebMethod]
    public bool ValidateUserPassword(int userID, string password)
    {
        return true;
    }

//    [WebMethod]   
//    public void Test()
//    {
//        var dir = @"C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures";
//        var files = Directory.GetFiles(dir, "*.jpg");
//        using (var c = DBUtils.CreateDataAbstaction())
//        {
//            var cn = c.Connection;
//            if (cn.State != ConnectionState.Open)
//                cn.Open();
//            var cmd = (SqlCommand)cn.CreateCommand();
//            cmd.CommandType = CommandType.Text;
//            cmd.CommandText = "INSERT INTO [MOBJECT] (ParentAlbumRef, Type, Data) VALUES (2, 0, @data)";
//            foreach (var s in files)
//            {
//                cmd.Parameters.AddWithValue("data", File.ReadAllBytes(s));
//                cmd.ExecuteNonQuery();
//                cmd.Parameters.Clear();
//                
//            }
//            c.SubmitChanges(ConflictMode.FailOnFirstConflict);
//        }
//    }

    public class TagTreeInfo
    {
        private class TagTreeBuilder
        {
            private readonly List<Tag> _Tags;

            public TagTreeBuilder(List<Tag> tags)
            {
                _Tags = tags;
            }

            public TagTreeInfo BuildRecursive(int? parentID)
            {
                List<TagTreeInfo> r = null;
                Func<List<TagTreeInfo>> getList = () =>
                {
                    if (r == null)
                    {
                        r = new List<TagTreeInfo>();
                    }
                    return r;
                };
                foreach (Tag t in _Tags)
                {
                    if (t.ParentID == parentID)
                    {
                        var treeItem = BuildRecursive(t.ID);
                        treeItem.Name = t.Name;
                        treeItem.ID = t.ID;
                        getList().Add(treeItem);
                    }
                }
                var res = new TagTreeInfo();
                if (r != null)
                    res.Children = r.ToArray();
                return res;
            }
        }

        public static TagTreeInfo FromList(List<Tag> tags)
        {
            if (tags == null)
                return null;
            return new TagTreeBuilder(tags).BuildRecursive(null);
        }

        public int ID { get; set; }
        public string Name { get; set; }
        public TagTreeInfo[] Children { get; set; }
    }
}

